package com.syncomponents.client.http;

import java.io.IOException;
import java.nio.charset.Charset;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.fluentx.Request;
import org.apache.http.client.fluentx.UrlBuilder;
import org.apache.http.entity.ContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.syncomponents.client.MessageHelper;
import com.syncomponents.core.RequestException;
import com.syncomponents.remoting.HttpMessage;
import com.syncomponents.util.BaseConstant;

import commonj.sdo.DataObject;

/**
 * http 客户端
 * 
 * @author sunkey
 * @date Mar 31, 2014
 */
public class HttpClient {

    private final static Logger LOGGER = LoggerFactory.getLogger(HttpClient.class);

    /**
     * 执行请求, 需要传入返回类型
     * 
     * @param messageRequest
     * @param classType only support String, byte[], DataObject
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T doExcute(HttpMessage messageRequest, Class<T> returnType) {
        LOGGER.info("messageRequest:{}", messageRequest.toString());
        if (returnType == null) {
            throw new IllegalArgumentException("returnType is required");
        }

        try {
            LOGGER.info("request url:{}", messageRequest.getHttpHost().toHostString() + messageRequest.getPath());

            LOGGER.info("messageRequest:{}", messageRequest.toString());
            HttpResponse httpResponse = execute(messageRequest);

            T response = null;
            if (returnType.equals(DataObject.class)) {
                return (T) MessageHelper.toDataObject(httpResponse.getEntity());
            } else if (returnType.isArray()) {
                response = (T) MessageHelper.toByteArray(httpResponse.getEntity());
            } else {
                response = (T) MessageHelper.toString(httpResponse.getEntity());
            }

            LOGGER.info("request url:{}, response:{}",
                    messageRequest.getHttpHost().toHostString() + messageRequest.getPath(), response);

            return (T) response;
        } catch (IOException e) {
            throw new RequestException(e.getMessage(), e);
        } catch (ClassNotFoundException e) {
            throw new RequestException(e.getMessage(), e);
        }
    }

    private Request getRequest(HttpMessage messageRequest) {
        final String uri = UrlBuilder.url(messageRequest.getHttpHost(), messageRequest.getPath()).build();
        Request request = Request.Post(uri);
        if (messageRequest.getContent() != null) {
            request.bodyString(messageRequest.getContent().toString(),
                    ContentType.create(messageRequest.getContentType(), Charset.forName(BaseConstant.ENCODE_TYPE_UTF8)));
        }
        return request;
    }

    /**
     * 执行请求
     * 
     * @param httpRequst 请求类
     * @return 返回消息
     */
    private HttpResponse execute(HttpMessage messageRequest) {
        LOGGER.info("request url:{}", messageRequest.getHttpHost().toHostString());
        try {
            return getRequest(messageRequest).execute().returnResponse();
        } catch (ClientProtocolException e) {
            LOGGER.error(e.getMessage(), e);
            throw new RequestException(e.getMessage(), e);
        } catch (IOException e) {
            LOGGER.error(e.getMessage(), e);
            throw new RequestException(e.getMessage(), e);
        }
    }

}
